<script setup lang="ts">
import { ref, computed, watch, onMounted, onUnmounted } from 'vue';
import { CaretRight, CaretBottom } from '@element-plus/icons-vue';
import { useGraphStore } from '@/store/kg/graph';

// 声明window上的graph属性类型
declare global {
  interface Window {
    graph: any;
  }
}

// 使用pinia store
const graphStore = useGraphStore();

// 图例展开状态
const expanded = ref(true);

// 创建节点类型和边类型的筛选状态集合
const filteredNodeTypes = ref(new Set<string>());
const filteredEdgeTypes = ref(new Set<string>());

// 从store获取节点类型和边
const nodeTypes = computed(() => graphStore.nodeTypes);
const edgeTypes = computed(() => graphStore.edgeTypes || []);

// 图例位置
defineProps({
  position: {
    type: String,
    default: 'top-left'
  }
});

// 定义节点类型对应的颜色
const nodeTypeColors: Record<string, string> = {
  'Course': '#FF6B3B',   // 橙色
  'Case': '#d1db12',     // 黄色
  'Component': '#9661BC', // 紫色
  'Knowledge': '#60C0DD', // 蓝色
  'default': '#5B8FF9'   // 默认蓝色
};

// 定义边类型对应的颜色
const edgeTypeColors: Record<string, string> = {
  'PRE_COURSE': '#FF9500',        // 橙色
  'COURSE_KNOWLEDGE': '#1890FF',  // 蓝色
  'PRE_KNOWLEDGE': '#52C41A',     // 绿色
  'CASE_COMPONENT': '#722ED1',    // 紫色
  'RELATED': '#F5222D',           // 红色
  'default': '#8C8C8C'            // 默认灰色
};

// 定义边类型是否使用虚线
const edgeTypeDashed: Record<string, boolean> = {
  'PRE_COURSE': false,
  'COURSE_KNOWLEDGE': false,
  'PRE_KNOWLEDGE': true,  // 前置知识使用虚线
  'CASE_COMPONENT': false,
  'RELATED': true,        // 关联关系使用虚线
  'default': false
};

// 关系名称到关系类型的映射表
const relationNameToType: Record<string, string> = {
  '前置课程': 'PRE_COURSE',
  '包含知识点': 'COURSE_KNOWLEDGE',
  '前置知识点': 'PRE_KNOWLEDGE',
  '包含组件': 'CASE_COMPONENT',
  '关联': 'RELATED'
};

// 获取节点类型颜色
const getNodeTypeColor = (type: string) => {
  return nodeTypeColors[type] || nodeTypeColors.default;
};

// 获取边类型颜色
const getEdgeTypeColor = (type: string) => {
  return edgeTypeColors[type] || edgeTypeColors.default;
};

// 获取边类型是否使用虚线
const isEdgeTypeDashed = (type: string) => {
  return edgeTypeDashed[type] || edgeTypeDashed.default;
};

// 切换图例展开/收起状态
const toggleExpand = () => {
  expanded.value = !expanded.value;
};

// 筛选节点类型
const filterNodeType = (type: string) => {
  if (filteredNodeTypes.value.has(type)) {
    filteredNodeTypes.value.delete(type);
  } else {
    filteredNodeTypes.value.add(type);
  }
  applyFilters();
};

// 筛选边类型
const filterEdgeType = (type: string) => {
  if (filteredEdgeTypes.value.has(type)) {
    filteredEdgeTypes.value.delete(type);
    console.log(`从筛选集合中移除边类型: ${type}`);
  } else {
    filteredEdgeTypes.value.add(type);
    console.log(`添加边类型到筛选集合: ${type}`);
  }
  console.log('当前筛选的边类型集合:', Array.from(filteredEdgeTypes.value));
  applyFilters();
};

// 根据边的数据获取其关系类型
const getEdgeRelationType = (edge: any) => {
  const model = edge.getModel();
  // 从边的name属性获取关系类型
  if (model.name) {
    return relationNameToType[model.name] || model.name;
  }
  // 从边的label属性获取关系类型
  if (model.label) {
    return relationNameToType[model.label] || model.label;
  }
  // 检查是否有relationshipType字段
  if (model.data && model.data.relationshipType) {
    return model.data.relationshipType;
  }
  // 检查是否有type字段且非'line'
  if (model.type && model.type !== 'line') {
    return model.type;
  }
  // 最终返回未知类型
  return 'unknown';
};

// 判断边是否应该被筛选（隐藏）
const shouldFilterEdge = (edge: any) => {
  const model = edge.getModel();
  console.log('边数据:', model);

  // 获取边的关系类型
  const relationType = getEdgeRelationType(edge);
  console.log(`边 ${model.id} 的关系类型: ${relationType}`);

  // 只有当关系类型在筛选集合中时，返回true表示应该筛选/隐藏此边
  return filteredEdgeTypes.value.has(relationType);
};

// 应用筛选器更新图形显示
const applyFilters = () => {
  if (!window.graph) {
    console.warn('graph对象不存在，无法应用筛选');
    return;
  }

  const graph = window.graph;
  const nodes = graph.getNodes();
  const edges = graph.getEdges();

  console.log(`开始应用筛选 - 节点数量: ${nodes.length}, 边数量: ${edges.length}`);
  console.log('筛选的节点类型:', Array.from(filteredNodeTypes.value));
  console.log('筛选的边类型:', Array.from(filteredEdgeTypes.value));

  // 创建一个隐藏的节点ID集合，用于后续判断边的显示
  const hiddenNodeIds = new Set<string>();

  // 处理节点
  nodes.forEach((node: any) => {
    const model = node.getModel();
    const visible = !filteredNodeTypes.value.has(model.type);

    // 更新节点隐藏状态
    graph.updateItem(node, {
      visible
    });

    // 如果节点被隐藏，记录其ID
    if (!visible) {
      hiddenNodeIds.add(model.id);
    }
  });

  console.log(`隐藏的节点ID数量: ${hiddenNodeIds.size}`);

  // 处理边
  let hiddenEdgesCount = 0;
  edges.forEach((edge: any) => {
    const model = edge.getModel();
    console.log(`处理边 - ID: ${model.id}, 类型: ${model.type}, 源节点: ${model.source}, 目标节点: ${model.target}`);

    // 使用新的方法判断边是否应该被筛选
    const typeFiltered = shouldFilterEdge(edge);
    const sourceHidden = hiddenNodeIds.has(model.source);
    const targetHidden = hiddenNodeIds.has(model.target);

    const visible = !typeFiltered && !sourceHidden && !targetHidden;

    console.log(`边状态 - 类型被筛选: ${typeFiltered}, 源节点隐藏: ${sourceHidden}, 目标节点隐藏: ${targetHidden}, 最终可见性: ${visible}`);

    // 更新边的隐藏状态
    graph.updateItem(edge, {
      visible
    });

    if (!visible) {
      hiddenEdgesCount++;
    }
  });

  console.log(`筛选完成 - 隐藏的边数量: ${hiddenEdgesCount}`);
};

// 处理来自主视图的应用筛选请求
const handleApplyFilters = () => {
  console.log('接收到应用筛选事件，重新应用筛选条件');
  applyFilters();
};

// 组件挂载时添加事件监听
onMounted(() => {
  window.addEventListener('applyGraphFilters', handleApplyFilters);
});

// 组件卸载时移除事件监听
onUnmounted(() => {
  window.removeEventListener('applyGraphFilters', handleApplyFilters);
});

// 监听筛选条件变化
watch(
  [filteredNodeTypes, filteredEdgeTypes],
  () => {
    applyFilters();
  },
  { deep: true }
);

// 默认导出组件
defineOptions({
  name: 'KgLegend'
});

// 导出供其他组件调用的方法
defineExpose({
  applyFilters,
  filterNodeType,
  filterEdgeType,
  filteredNodeTypes,
  filteredEdgeTypes
});
</script>

<template>
  <div class="kg-legend" :class="position">
    <div class="legend-header" @click="toggleExpand">
      <el-icon v-if="expanded"><CaretBottom /></el-icon>
      <el-icon v-else><CaretRight /></el-icon>
      <span>图例</span>
    </div>
    <div v-if="expanded" class="legend-content">
      <div v-if="nodeTypes.length > 0" class="legend-section">
        <div class="section-title">节点类型:</div>
        <div class="legend-items">
          <div
            v-for="type in nodeTypes"
            :key="type.type"
            class="legend-item"
            :class="{ filtered: filteredNodeTypes.has(type.type) }"
            @click="filterNodeType(type.type)"
          >
            <span class="item-color" :style="{ backgroundColor: getNodeTypeColor(type.type) }"></span>
            <span class="item-name">{{ type.name }}</span>
          </div>
        </div>
      </div>

      <div v-if="edgeTypes.length > 0" class="legend-section">
        <div class="section-title">关系类型:</div>
        <div class="legend-items">
          <div
            v-for="type in edgeTypes"
            :key="type.type"
            class="legend-item"
            :class="{ filtered: filteredEdgeTypes.has(type.type) }"
            @click="filterEdgeType(type.type)"
          >
            <span 
              v-if="isEdgeTypeDashed(type.type)"
              class="item-line dashed-line"
              :style="{ borderTopColor: getEdgeTypeColor(type.type) }"
            >
              <span class="item-arrow" :style="{ borderLeftColor: getEdgeTypeColor(type.type) }"></span>
            </span>
            <span 
              v-else
              class="item-line"
              :style="{ backgroundColor: getEdgeTypeColor(type.type) }"
            >
              <span class="item-arrow" :style="{ borderLeftColor: getEdgeTypeColor(type.type) }"></span>
            </span>
            <span class="item-name">{{ type.name }}</span>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">
.kg-legend {
  position: absolute;
  z-index: 1000;
  background: rgba(255, 255, 255, 0.9);
  border-radius: 4px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  min-width: 150px;
  max-width: 250px;
  transition: all 0.3s ease;
  overflow: hidden;

  &.top-left {
    top: 80px;
    left: 20px;
  }

  &.top-right {
    top: 80px;
    right: 20px;
  }

  .legend-header {
    display: flex;
    align-items: center;
    padding: 8px 12px;
    background-color: #f5f7fa;
    cursor: pointer;
    user-select: none;
    border-bottom: 1px solid #e4e7ed;

    &:hover {
      background-color: #e4e7ed;
    }

    .el-icon {
      margin-right: 8px;
      font-size: 16px;
    }

    span {
      font-weight: 500;
      color: #303133;
    }
  }

  .legend-content {
    padding: 8px 0;
    max-height: 500px; /* 增加最大高度，确保能显示所有图例 */
    overflow-y: auto;

    .legend-section {
      margin-bottom: 8px;

      &:last-child {
        margin-bottom: 0;
      }

      .section-title {
        padding: 4px 12px;
        font-size: 13px;
        color: #606266;
        font-weight: 500;
      }

      .legend-items {
        .legend-item {
          display: flex;
          align-items: center;
          padding: 6px 12px;
          cursor: pointer;
          transition: background-color 0.2s;

          &:hover {
            background-color: #f5f7fa;
          }

          &.filtered {
            opacity: 0.5;
            text-decoration: line-through;
          }

          .item-color {
            width: 16px;
            height: 16px;
            border-radius: 50%;
            margin-right: 8px;
          }

          .item-line {
            position: relative;
            width: 20px;
            height: 2px;
            margin-right: 8px;
            display: flex;
            align-items: center;
            justify-content: flex-end;

            &.dashed-line {
              background-color: transparent;
              border-top: 2px dashed;
              height: 0;
            }

            .item-arrow {
              position: absolute;
              right: -4px;
              width: 0;
              height: 0;
              border-left: 6px solid currentColor;
              border-top: 4px solid transparent;
              border-bottom: 4px solid transparent;
            }
          }

          .item-name {
            font-size: 13px;
            color: #303133;
          }
        }
      }
    }
  }
}
</style>
